package fedex;

import java.util.Calendar;

import org.apache.axis.types.PositiveInteger;

import com.fedex.addressvalidation.stub.Address;
import com.fedex.addressvalidation.stub.AddressToValidate;
import com.fedex.addressvalidation.stub.AddressValidationAccuracyType;
import com.fedex.addressvalidation.stub.AddressValidationChangeType;
import com.fedex.addressvalidation.stub.AddressValidationOptions;
import com.fedex.addressvalidation.stub.AddressValidationPortType;
import com.fedex.addressvalidation.stub.AddressValidationReply;
import com.fedex.addressvalidation.stub.AddressValidationRequest;
import com.fedex.addressvalidation.stub.AddressValidationResult;
import com.fedex.addressvalidation.stub.AddressValidationServiceLocator;
import com.fedex.addressvalidation.stub.ClientDetail;
import com.fedex.addressvalidation.stub.Notification;
import com.fedex.addressvalidation.stub.NotificationSeverityType;
import com.fedex.addressvalidation.stub.ProposedAddressDetail;
import com.fedex.addressvalidation.stub.ResidentialStatusType;
import com.fedex.addressvalidation.stub.TransactionDetail;
import com.fedex.addressvalidation.stub.VersionId;
import com.fedex.addressvalidation.stub.WebAuthenticationCredential;
import com.fedex.addressvalidation.stub.WebAuthenticationDetail;


/** 
 * Sample code to call the FedEx Address validation Web Service
 * <p>
 * com.fedex.addressvalidation.stub is generated via WSDL2Java, like this:<br>
 * <pre>
 * java org.apache.axis.wsdl.WSDL2Java -w -p com.fedex.addressvalidation.stub http://www.fedex.com/...../AddressValidationService?wsdl
 * </pre>
 * 
 * This sample code has been tested with JDK 5 and Apache Axis 1.4
 */
public class AddressValidationWebServiceClient {
    
    //my register
    public static String accountNumber = "xx";
    public static String meterNumber = "xx";
    public static String key = "xx";
    public static String password= "xx"; //new password

    
	public static void main(String[] args) { 
	    //
		AddressValidationRequest request = new AddressValidationRequest();
        request.setClientDetail(createClientDetail());
        request.setWebAuthenticationDetail(createWebAuthenticationDetail());
        //
        VersionId versionId = new VersionId("aval", 2, 0, 0);
        request.setVersion(versionId);
	    //
	    TransactionDetail transactionDetail = new TransactionDetail();
	    transactionDetail.setCustomerTransactionId("java sample - AddressValidationRequest"); //This is a reference field for the customer.  Any value can be used and will be provided in the return.
	    request.setTransactionDetail(transactionDetail);
        //
	    Calendar c = Calendar.getInstance();
	    request.setRequestTimestamp(c);
        //
	    AddressValidationOptions vo = new AddressValidationOptions();
	    vo.setCheckResidentialStatus(new Boolean(true));
	    vo.setMaximumNumberOfMatches(new PositiveInteger("5"));
	    vo.setStreetAccuracy(AddressValidationAccuracyType.LOOSE);
	    vo.setDirectionalAccuracy(AddressValidationAccuracyType.LOOSE);
	    vo.setCompanyNameAccuracy(AddressValidationAccuracyType.LOOSE);
	    vo.setConvertToUpperCase(new Boolean(true));
	    vo.setRecognizeAlternateCityNames(new Boolean(true));
	    vo.setReturnParsedElements(new Boolean(true));
	    request.setOptions(vo);
	    
	    AddressToValidate av1 = new AddressToValidate();
	    Address business = new Address();
	    //business.setStreetLines(new String[] {"10 FedEx Parkway"});
	    //business.setPostalCode("38017");
	    //a1.setPostalCode("38017");
	    //a1.setCountryCode("CA");
	    business.setStreetLines(new String[] {"4114 Sepulveda Blvd."});
        business.setPostalCode("90230");
	    
	    av1.setAddress(business);
	    av1.setAddressId("Ship To Address");
	    
	    
	    AddressToValidate av2 = new AddressToValidate();
	    Address home = new Address();
	    home.setStreetLines(new String[] {"1074 Beechcroft Rd"});
	    home.setPostalCode("37174");
	    home.setStateOrProvinceCode("TN");
	    av2.setAddress(home);
	    av2.setAddressId("Home");
	    
	    /*
	    AddressToValidate av1 = new AddressToValidate();
        Address a1 = new Address();
        a1.setStreetLines(new String[] {"Address Line 1"});
        a1.setCity("City Name");
        a1.setStateOrProvinceCode("QC");
        a1.setPostalCode("H1E1A1");
        a1.setCountryCode("CA");
        */
        
        //av1.setCompanyName("FedEx Services");
        //av1.setAddressId("Target Address");
	    
	    request.setAddressesToValidate(new AddressToValidate[] {av1,av2});
	    //
		try {
			// Initialize the service
			AddressValidationServiceLocator service;
			AddressValidationPortType port;
			//	
			service = new AddressValidationServiceLocator();
			updateEndPoint(service);
			System.out.println(service.getAddressValidationServicePortAddress());
			port = service.getAddressValidationServicePort();	
			// This is the call to the web service
			AddressValidationReply reply = port.addressValidation(request);
			VersionId vid = reply.getVersion();
			System.out.println("version major: " + vid.getMajor());
			System.out.println("version intermediate: " + vid.getIntermediate());
			System.out.println("version minor: "+ vid.getMinor());
			//
			if (isResponseOk(reply.getHighestSeverity()))
			{
				AddressValidationResult[] avr = reply.getAddressResults();
				for(int i = 0; i < avr.length; i++)
				{
				    System.out.println("==== i === "+i);
					System.out.println("Address Id - " + avr[i].getAddressId());
					System.out.println("--- Proposed details ---");
					ProposedAddressDetail[] ad1 = avr[i].getProposedAddressDetails();
					for(int j = 0; j < ad1.length; j++)
					{
						System.out.println("j="+j+"  Score - " + ad1[j].getScore());
						
						ResidentialStatusType res=ad1[j].getResidentialStatus();
						if(res != null){
						    System.out.println("  Residential - "+res.getValue());
						    System.out.println(ResidentialStatusType.fromString("RESIDENTIAL"));
						}
						
						System.out.println("  Address - " + ad1[j].getAddress().getStreetLines(0));
						System.out.println("  State:"+ad1[j].getAddress().getStateOrProvinceCode());
						System.out.println("  Postal:"+ad1[j].getAddress().getPostalCode());
						System.out.println("  Country:"+ad1[j].getAddress().getCountryCode());
						System.out.println("  City:"+ad1[j].getAddress().getCity());
						System.out.println("  Urban:"+ad1[j].getAddress().getUrbanizationCode());
						System.out.println("  Residential:"+ad1[j].getAddress().getResidential());
						
						System.out.println("  Changes - " + ad1[j].getScore());
						AddressValidationChangeType[] avct = ad1[j].getChanges();
						for(int k = 0; k < avct.length; k++)
						{
							System.out.println("    "+avct[k].toString());
						}
					}
				}
			}

			printNotifications(reply.getNotifications());

		} catch (Exception e) {
            e.printStackTrace();
		}
	}

	private static boolean isResponseOk(NotificationSeverityType notificationSeverityType) {
		if (notificationSeverityType == null) {
			return false;
		}
		if (notificationSeverityType.equals(NotificationSeverityType.WARNING) ||
			notificationSeverityType.equals(NotificationSeverityType.NOTE)    ||
			notificationSeverityType.equals(NotificationSeverityType.SUCCESS)) {
			return true;
		}
 		return false;
	}

	private static ClientDetail createClientDetail() {
        ClientDetail clientDetail = new ClientDetail();

        clientDetail.setAccountNumber(accountNumber);
        clientDetail.setMeterNumber(meterNumber);
        return clientDetail;
	}
	
	private static WebAuthenticationDetail createWebAuthenticationDetail() {
        WebAuthenticationCredential wac = new WebAuthenticationCredential();

        wac.setKey(key);
        wac.setPassword(password);
		return new WebAuthenticationDetail(wac);
	}
	
	private static void printNotifications(Notification[] notifications) {
		System.out.println("Notifications:");
		if (notifications == null || notifications.length == 0) {
			System.out.println("  No notifications returned");
		}
		for (int i=0; i < notifications.length; i++){
			Notification n = notifications[i];
			System.out.print("  Notification no. " + i + ": ");
			if (n == null) {
				System.out.println("null");
				continue;
			} else {
				System.out.println("");
			}
			NotificationSeverityType nst = n.getSeverity();

			System.out.println("    Severity: " + (nst == null ? "null" : nst.getValue()));
			System.out.println("    Code: " + n.getCode());
			System.out.println("    Message: " + n.getMessage());
			System.out.println("    Source: " + n.getSource());
		}
	}
	
	private static void updateEndPoint(AddressValidationServiceLocator serviceLocator) {
		String endPoint = System.getProperty("endPoint");
		if (endPoint != null) {
			serviceLocator.setAddressValidationServicePortEndpointAddress(endPoint);
		}
	}
	
}
